﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Drawing;

using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.CV.GPU;

namespace WpfFaceDetectionTest
{
    public static class Recognition
    {
        private static Dictionary<int, string> haarPaths;

        public static void Initialize()
        {
            haarPaths = new Dictionary<int, string>();

            haarPaths.Add(0, "haarcascade_frontalface_default.xml");
        }

        public static List<Rectangle> Detect(Image<Gray, Byte> image, RecognitionType type, int? height = null, int? width = null)
        {
            var items = new List<Rectangle>();

            if (GpuInvoke.HasCuda)
                using (var detectedItems = new GpuCascadeClassifier(haarPaths[(int)type]))
                {
                    using (var gpuImage = new GpuImage<Bgr, byte>(image))
                    {
                        items = detectedItems.DetectMultiScale(gpuImage, 1.1, 10, Size.Empty).ToList();
                    }
                }
            else
                using (var detectedItems = new CascadeClassifier(haarPaths[(int)type]))
                {
                    using (image)
                    {
                        image._EqualizeHist();
                        items = detectedItems.DetectMultiScale(image, 1.1, 10, new Size(20, 20), Size.Empty).ToList();
                    }
                }

            return items;
        }

        private static List<Rectangle> DetectFacesFast(Image<Gray, Byte> image, RecognitionType type, int height = 0, int width = 0)
        {
            var recogObjects = new List<Rectangle>();

            using (var faces = new CascadeClassifier(haarPaths[(int)type]))
            {
                using (image)
                {
                    if (height != 0 && width != 0)
                    {
                        image = image.Resize(height, width, INTER.CV_INTER_CUBIC);
                    }
                    else
                    {
                        image = image.Resize(620, 440, INTER.CV_INTER_CUBIC);
                    }
                    image._EqualizeHist();
                    recogObjects = faces.DetectMultiScale(image, 1.2, 10, new Size(50, 50), Size.Empty).ToList();
                }
            }

            return recogObjects;
        }

        public static bool HasDetected(Image<Gray, Byte> image, RecognitionType type)
        {
            if (DetectFacesFast(image, type).Count > 0)
                return true;
            return false;
        }
    }
}
